/*
 * @Author: Du Weixing duweixing@sgsimulation.com
 * @Date: 2024-08-05 15:04:53
 * @LastEditors: Du Weixing duweixing@sgsimulation.com
 * @LastEditTime: 2024-08-06 16:02:07
 * @FilePath: \SGFEM\Solver\BeamSecPropCalculator\test\SectionMesherTest.hpp
 * @Description: 
 * 
 * Copyright (c) 2024 by 神工仿真, All Rights Reserved. 
 */

#include "gtest/gtest.h"
#include "DataStructure/Common/Real.h"
#include "../StandardSectionTool.h"

using SG::DataStructure::Common::Real;
using SG::Algebra::Point;
using namespace SG::FEMSolver::Element;

TEST (SectionMesherTest, MeshRect)
{
    // Input data
    Point point{0.0, 1.0, 2.0};
    Real a{4.0}, b{4.0};
    int Na{2}, Nb{2}, nodeId0{0}, eleId0{0};

    // Test data
    Meshes meshesTest;
    NodeSet edgeNodesTest;
    StandardSectionTool::MeshRect (point, a, b, Na, Nb, nodeId0, eleId0, _OUT meshesTest, _OUT edgeNodesTest);

    // Target data
    Meshes meshesTarget;
    meshesTarget.nodes = {
        { 1, 1.0, 2.0}, { 2, 1.0, 3.0}, { 3, 1.0, 4.0}, { 4, 1.0, 5.0}, { 5, 1.0, 6.0},
        { 6, 2.0, 2.0}, { 7, 2.0, 3.0}, { 8, 2.0, 4.0}, { 9, 2.0, 5.0}, {10, 2.0, 6.0},
        {11, 3.0, 2.0}, {12, 3.0, 3.0}, {13, 3.0, 4.0}, {14, 3.0, 5.0}, {15, 3.0, 6.0},
        {16, 4.0, 2.0}, {17, 4.0, 3.0}, {18, 4.0, 4.0}, {19, 4.0, 5.0}, {20, 4.0, 6.0},
        {21, 5.0, 2.0}, {22, 5.0, 3.0}, {23, 5.0, 4.0}, {24, 5.0, 5.0}, {25, 5.0, 6.0}};
    meshesTarget.q9Elements = {
        {1, { 1, 11, 13,  3,  6, 12,  8,  2,  7}},
        {2, { 3, 13, 15,  5,  8, 14, 10,  4,  9}},
        {3, {11, 21, 23, 13, 16, 22, 18, 12, 17}},
        {4, {13, 23, 25, 15, 18, 24, 20, 14, 19}}};
    NodeSet edgeNodesTarget{
        { 1, 1.0, 2.0}, { 2, 1.0, 3.0}, { 3, 1.0, 4.0}, { 4, 1.0, 5.0},
        { 5, 1.0, 6.0}, { 6, 2.0, 2.0}, {10, 2.0, 6.0}, {11, 3.0, 2.0},
        {15, 3.0, 6.0}, {16, 4.0, 2.0}, {20, 4.0, 6.0}, {21, 5.0, 2.0},
        {22, 5.0, 3.0}, {23, 5.0, 4.0}, {24, 5.0, 5.0}, {25, 5.0, 6.0}};

    // Check
    ASSERT_TRUE (meshesTarget == meshesTest);
    ASSERT_TRUE (edgeNodesTarget == edgeNodesTest);
}

TEST (SectionMesherTest, MeshRect2)
{
    // Input data
    Point point{0.0, 1.0, 2.0};
    Real a{4.0}, b{4.0};
    int Na{2}, Nb{2}, nodeId0{0}, eleId0{0};

    // Test data
    Meshes meshesTest;
    NodeSet edgeNodesTest;
    StandardSectionTool::MeshRect2 (point, a, b, Na, Nb, nodeId0, eleId0, _OUT meshesTest, _OUT edgeNodesTest);

    // Target data
    Meshes meshesTarget;
    meshesTarget.nodes = {
        { 1, 1.0, 2.0}, { 2, 2.0, 2.0}, { 3, 3.0, 2.0}, { 4, 4.0, 2.0}, { 5, 5.0, 2.0},
        { 6, 1.0, 3.0}, { 7, 2.0, 3.0}, { 8, 3.0, 3.0}, { 9, 4.0, 3.0}, {10, 5.0, 3.0},
        {11, 1.0, 4.0}, {12, 2.0, 4.0}, {13, 3.0, 4.0}, {14, 4.0, 4.0}, {15, 5.0, 4.0},
        {16, 1.0, 5.0}, {17, 2.0, 5.0}, {18, 3.0, 5.0}, {19, 4.0, 5.0}, {20, 5.0, 5.0},
        {21, 1.0, 6.0}, {22, 2.0, 6.0}, {23, 3.0, 6.0}, {24, 4.0, 6.0}, {25, 5.0, 6.0}};
    meshesTarget.q9Elements = {
        {1, { 1,  3, 13, 11,  2,  8, 12,  6,  7}},
        {2, { 3,  5, 15, 13,  4, 10, 14,  8,  9}},
        {3, {11, 13, 23, 21, 12, 18, 22, 16, 17}},
        {4, {13, 15, 25, 23, 14, 20, 24, 18, 19}}};
    NodeSet edgeNodesTarget{
        { 1, 1.0, 2.0}, { 2, 2.0, 2.0}, { 3, 3.0, 2.0}, { 4, 4.0, 2.0},
        { 5, 5.0, 2.0}, { 6, 1.0, 3.0}, {10, 5.0, 3.0}, {11, 1.0, 4.0},
        {15, 5.0, 4.0}, {16, 1.0, 5.0}, {20, 5.0, 5.0}, {21, 1.0, 6.0},
        {22, 2.0, 6.0}, {23, 3.0, 6.0}, {24, 4.0, 6.0}, {25, 5.0, 6.0}};

    // Check
    ASSERT_TRUE (meshesTarget == meshesTest);
    ASSERT_TRUE (edgeNodesTarget == edgeNodesTest);
}

TEST (SectionMesherTest, Merge)
{
    // Input data
    int numFrontRepeatNodes{3}, numLastRepeatNodes{3}, nodeIdTest{18}, eleIdTest{2};
    NodeSet edgeNodes{
        { 1, 1.0, 2.0}, { 2, 1.0, 3.0}, { 3, 1.0, 4.0},
        { 4, 2.0, 2.0},                 { 6, 2.0, 4.0},
        { 7, 3.0, 2.0}, { 8, 3.0, 3.0}, { 9, 3.0, 4.0},
        {10, 5.0, 2.0}, {11, 5.0, 3.0}, {12, 5.0, 4.0},
        {13, 6.0, 2.0},                 {15, 6.0, 4.0},
        {16, 7.0, 2.0}, {17, 7.0, 3.0}, {18, 7.0, 4.0}};
    Meshes meshesTest, newMeshes;
    meshesTest.nodes = {
        { 1, 1.0, 2.0}, { 2, 1.0, 3.0}, { 3, 1.0, 4.0},
        { 4, 2.0, 2.0}, { 5, 2.0, 3.0}, { 6, 2.0, 4.0},
        { 7, 3.0, 2.0}, { 8, 3.0, 3.0}, { 9, 3.0, 4.0},
        {10, 5.0, 2.0}, {11, 5.0, 3.0}, {12, 5.0, 4.0},
        {13, 6.0, 2.0}, {14, 6.0, 3.0}, {15, 6.0, 4.0},
        {16, 7.0, 2.0}, {17, 7.0, 3.0}, {18, 7.0, 4.0}};
    meshesTest.q9Elements = {{1, {1, 7, 9, 3, 4, 8, 6, 2, 5}}, {2, {10, 16, 18, 12, 13, 17, 15, 11, 14}}};
    newMeshes.nodes = {
        { 7, 3.0, 2.0}, { 8, 3.0, 3.0}, { 9, 3.0, 4.0},
        {19, 4.0, 2.0}, {20, 4.0, 3.0}, {21, 4.0, 4.0},
        {22, 5.0, 2.0}, {23, 5.0, 3.0}, {24, 5.0, 4.0}};
    newMeshes.q9Elements = {{3, {7, 22, 24, 9, 19, 23, 21, 8, 20}}};

    // Test data
    StandardSectionTool::Merge (edgeNodes, numLastRepeatNodes, newMeshes, _OUT meshesTest, _OUT nodeIdTest, _OUT eleIdTest, numFrontRepeatNodes);

    // Target data
    Meshes meshesTarget;
    meshesTarget.nodes = {
        { 1, 1.0, 2.0}, { 2, 1.0, 3.0}, { 3, 1.0, 4.0},
        { 4, 2.0, 2.0}, { 5, 2.0, 3.0}, { 6, 2.0, 4.0},
        { 7, 3.0, 2.0}, { 8, 3.0, 3.0}, { 9, 3.0, 4.0},
        {10, 5.0, 2.0}, {11, 5.0, 3.0}, {12, 5.0, 4.0},
        {13, 6.0, 2.0}, {14, 6.0, 3.0}, {15, 6.0, 4.0},
        {16, 7.0, 2.0}, {17, 7.0, 3.0}, {18, 7.0, 4.0},
        {19, 4.0, 2.0}, {20, 4.0, 3.0}, {21, 4.0, 4.0}};
    meshesTarget.q9Elements = {
        {1, { 1,  7,  9,  3,  4,  8,  6,  2,  5}},
        {2, {10, 16, 18, 12, 13, 17, 15, 11, 14}},
        {3, { 7, 10, 12,  9, 19, 11, 21,  8, 20}}};
    int nodeIdTarget{21}, eleIdTarget{3};

    // Check
    ASSERT_TRUE (meshesTarget == meshesTest);
    ASSERT_TRUE (nodeIdTarget == nodeIdTest);
    ASSERT_TRUE (eleIdTarget == eleIdTest);
}

TEST (SectionMesherTest, Merge2)
{
    // Input data
    int numFrontRepeatNodes{3};
    NodeSet edgeNodes{
        { 1, 1.0, 2.0}, { 2, 1.0, 3.0}, { 3, 1.0, 4.0},
        { 4, 2.0, 2.0}, { 5, 2.0, 3.0}, { 6, 2.0, 4.0},
        { 7, 3.0, 2.0}, { 8, 3.0, 3.0}, { 9, 3.0, 4.0},
        {10, 5.0, 2.0}, {11, 5.0, 3.0}, {12, 5.0, 4.0},
        {13, 6.0, 2.0}, {14, 6.0, 3.0}, {15, 6.0, 4.0},
        {16, 7.0, 2.0}, {17, 7.0, 3.0}, {18, 7.0, 4.0}};
    Meshes meshesTest;
    meshesTest.nodes = {
        {19, 3.0, 2.0}, {20, 3.0, 3.0}, {21, 3.0, 4.0},
        {22, 4.0, 2.0}, {23, 4.0, 3.0}, {24, 4.0, 4.0},
        {25, 5.0, 2.0}, {26, 5.0, 3.0}, {27, 5.0, 4.0}};
    meshesTest.q9Elements = {{3, {19, 25, 27, 21, 22, 26, 24, 20, 23}}};

    // Test data
    StandardSectionTool::Merge2 (edgeNodes, numFrontRepeatNodes, _OUT meshesTest);

    // Target data
    Meshes meshesTarget;
    meshesTarget.nodes = {
        { 7, 3.0, 2.0}, { 8, 3.0, 3.0}, { 9, 3.0, 4.0},
        {19, 4.0, 2.0}, {20, 4.0, 3.0}, {21, 4.0, 4.0},
        {22, 5.0, 2.0}, {23, 5.0, 3.0}, {24, 5.0, 4.0}};
    meshesTarget.q9Elements = {{3, {7, 22, 24, 9, 19, 23, 21, 8, 20}}};

    // Check
    ASSERT_TRUE (meshesTarget == meshesTest);
}

TEST (SectionMesherTest, UpdateEdgeNodes)
{
    // Input data
    int numLastRepeatNodes{3};
    NodeSet edgeNodesTest{
        {1, 1.0, 2.0}, {2, 1.0, 3.0}, {3, 1.0, 4.0},
        {4, 2.0, 2.0},                {6, 2.0, 4.0},
        {7, 3.0, 2.0}, {8, 3.0, 3.0}, {9, 3.0, 4.0}};
    NodeSet newEdgeNodes{
        {10, 5.0, 2.0}, {11, 5.0, 3.0}, {12, 5.0, 4.0},
        {13, 4.0, 2.0},                 {15, 4.0, 4.0},
        {16, 3.0, 2.0}, {17, 3.0, 3.0}, {18, 3.0, 4.0}};

    // Test data
    StandardSectionTool::UpdateEdgeNodes (newEdgeNodes, numLastRepeatNodes, _OUT edgeNodesTest);

    // Target data
    NodeSet edgeNodesTarget{
        { 1, 1.0, 2.0}, { 2, 1.0, 3.0}, { 3, 1.0, 4.0},
        { 4, 2.0, 2.0},                 { 6, 2.0, 4.0},
        { 7, 3.0, 2.0}, { 8, 3.0, 3.0}, { 9, 3.0, 4.0},
        {10, 5.0, 2.0}, {11, 5.0, 3.0}, {12, 5.0, 4.0},
        {13, 4.0, 2.0},                 {15, 4.0, 4.0}};

    // Check
    ASSERT_TRUE (edgeNodesTarget == edgeNodesTest);
}